package com.ict.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class LoggingInterceptor implements HandlerInterceptor {
    
    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    private static final ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 请求处理前执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        startTime.set(System.currentTimeMillis());
        
        // 包装请求以支持多次读取body
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
        
        // 收集请求信息
        Map<String, Object> requestInfo = new HashMap<>();
        requestInfo.put("URI", wrappedRequest.getRequestURI());
        requestInfo.put("ClientIP", getClientIp(wrappedRequest));
        requestInfo.put("Method", wrappedRequest.getMethod());
        requestInfo.put("Headers", getHeaders(wrappedRequest));
        requestInfo.put("Params", getParameters(wrappedRequest));
        requestInfo.put("Body", getRequestBody(wrappedRequest));

        logger.info("\n=== 请求信息 ===\n{}", formatLogData(requestInfo));
        return true;
    }

    /**
     * 请求处理后执行
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 包装响应以支持多次读取body
        ContentCachingResponseWrapper wrappedResponse = (ContentCachingResponseWrapper) response;

        // 收集响应信息
        Map<String, Object> responseInfo = new HashMap<>();
        responseInfo.put("Status", response.getStatus());
        responseInfo.put("Headers", getHeaders(response));
        responseInfo.put("Body", getResponseBody(wrappedResponse));
        responseInfo.put("TimeCost", System.currentTimeMillis() - startTime.get());

        logger.info("\n=== 响应信息 ===\n{}", formatLogData(responseInfo));
        
        // 清理ThreadLocal
        startTime.remove();
    }

    // 获取客户端真实IP
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    // 获取请求头信息
    private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, request.getHeader(headerName));
        }
        return headers;
    }


    // 获取请求参数（兼容GET/POST表单）
    private Map<String, String> getParameters(HttpServletRequest request) {
        Map<String, String> params = new LinkedHashMap<>();
        request.getParameterMap().forEach((key, values) -> {
            params.put(key, Arrays.toString(values));
        });
        return params;
    }

    // 获取请求体内容
    private String getRequestBody(ContentCachingRequestWrapper request) {
        try {
            byte[] buf = request.getContentAsByteArray();
            if (buf.length > 0) {
                return new String(buf, request.getCharacterEncoding());
            }
        } catch (UnsupportedEncodingException e) {
            logger.warn("Failed to parse request body", e);
        }
        return null;
    }

    // 获取响应头信息
    private Map<String, String> getHeaders(HttpServletResponse response) {
        Map<String, String> headers = new HashMap<>();
        for (String headerName : response.getHeaderNames()) {
            headers.put(headerName, response.getHeader(headerName));
        }
        return headers;
    }

    // 获取响应内容
    private String getResponseBody(ContentCachingResponseWrapper response) {
        try {
            byte[] buf = response.getContentAsByteArray();
            if (buf.length > 0) {
                // 强制使用UTF-8解码
                String payload = new String(buf, StandardCharsets.UTF_8);
                response.copyBodyToResponse();
                return payload;
            }
        } catch (IOException e) {
            logger.warn("Failed to parse response body", e);
        }
        return null;
    }

    // 格式化日志输出
    private String formatLogData(Map<String, Object> data) {
        StringBuilder sb = new StringBuilder();
        data.forEach((key, value) -> {
            String formattedValue = (value != null) ?
                    new String(value.toString().getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) : "";
            sb.append(String.format("%-10s: %s\n", key, formattedValue));
        });
        return sb.toString();
    }
}